﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Kugar.Core.ExtMethod;

namespace Kugar.Core.WinForm
{
    public class TreeViewBinding
    {
        private BaseStruct.Tree _tree = null;
        private List<TreeView> _treeViews = new List<TreeView>();
        private object _lockObj = new object();

        public TreeViewBinding(BaseStruct.Tree tree)
        {
            _tree = tree;

            _tree.Node_PropertyChanged += tree_Node_PropertyChanged;
            _tree.Node_NodeCollectionChanged += tree_Node_NodeCollectionChanged;

        }

        public void BindTo(TreeView treeView)
        {
            if (_treeViews.Contains(treeView))
            {
                return;
            }

            _treeViews.Add(treeView);

            lock (_lockObj)
            {
                initTreeView(treeView);
            }

        }

        public void UnBind(TreeView treeView)
        {
            lock (_lockObj)
            {
                _treeViews.Remove(treeView);
            }

        }

        private void initTreeView(TreeView treeView)
        {
            lock (_lockObj)
            {
                treeView.Invoke(() =>
                    {
                        treeView.Nodes.Clear();

                        foreach (var node in _tree)
                        {
                            var treeVewNode = treeNodeToTreeViewNode(node);

                            treeView.Nodes.Add(treeVewNode);

                            buildInternalTreeView(treeVewNode, node);
                        }
                    });
            }
        }

        private void buildInternalTreeView(TreeNode treeViewParentNode, BaseStruct.TreeNode parentNode)
        {
            if (!parentNode.IsLoaded)
            {
                return;
            }

            foreach (var node in parentNode.Nodes)
            {
                var treeViewNode = treeNodeToTreeViewNode(node);
                treeViewParentNode.Nodes.Add(treeViewNode);
                buildInternalTreeView(treeViewNode, node);
            }
        }

        private TreeNode treeNodeToTreeViewNode(BaseStruct.TreeNode node)
        {
            var treeVewNode = new TreeNode(node.Text);
            treeVewNode.Name = node.Key;
            treeVewNode.Text = node.Text;
            treeVewNode.Tag = node;

            return treeVewNode;
        }

        private void tree_Node_NodeCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs<BaseStruct.TreeNode> e)
        {
            var treeNode = (BaseStruct.TreeNode)sender;

            lock (_lockObj)
            {
                switch (e.Action)
                {
                    case NotifyCollectionChangedAction.Add:
                        if (e.NewItems.Count > 0)
                        {
                            foreach (var treeView in _treeViews)
                            {
                                treeView.Invoke(() =>
                                    {
                                        if (string.IsNullOrWhiteSpace(treeNode.Key))
                                        {
                                            e.NewItems.ForEachLoop(
                                                                                (s, x) =>
                                                                                    treeView.Nodes.Add(treeNodeToTreeViewNode((BaseStruct.TreeNode)x.Item))
                                                                                );
                                        }
                                        else
                                        {
                                            var treeViewNode = treeView.Nodes.Find(treeNode.Key, true).FirstOrDefault();

                                            if (treeViewNode!=null)
                                            {
                                                e.NewItems.ForEachLoop(
                                                (s, x) =>
                                                treeViewNode.Nodes.Add(treeNodeToTreeViewNode((BaseStruct.TreeNode)x.Item)));
                                            }
                                            
                                        }
                                    });
                            }
                        }
                        break;
                    case NotifyCollectionChangedAction.Remove:
                        if (e.NewItems.Count > 0)
                        {
                            foreach (var treeView in _treeViews)
                            {
                                treeView.Invoke(() =>
                                    {
                                        if (string.IsNullOrWhiteSpace(treeNode.Key))
                                        {
                                            e.NewItems.ForEachLoop(
                                                                                (s, x) =>
                                                                                    treeView.Nodes.RemoveByKey(((BaseStruct.TreeNode)x.Item).Key)
                                                                                );
                                        }
                                        else
                                        {
                                            var treeViewNode = treeView.Nodes.Find(treeNode.Key, true).FirstOrDefault();

                                            if (treeViewNode != null)
                                            {
                                                e.NewItems.ForEachLoop(
                                              (s, x) => treeViewNode.Nodes.RemoveByKey(((BaseStruct.TreeNode)x.Item).Key));
                                            }

                                        }
                                    });
                            }
                        }
                        break;
                    case NotifyCollectionChangedAction.Reset:
                        {
                            foreach (var treeView in _treeViews)
                            {
                                if (treeView==null)
                                {
                                    continue;
                                }

                                treeView.Invoke(() =>
                                    {
                                        if (string.IsNullOrWhiteSpace(treeNode.Key))
                                        {
                                            treeView.Nodes.Clear();

                                            if (e.NewItems.Count > 0)
                                            {
                                                e.NewItems.ForEachLoop(
                                                    (s, x) =>
                                                    treeView.Nodes.Add(treeNodeToTreeViewNode((BaseStruct.TreeNode)x.Item))
                                                    );
                                            }
                                        }
                                        else
                                        {
                                            var treeViewNode = treeView.Nodes.Find(treeNode.Key, true).First();

                                            treeViewNode.Nodes.Clear();

                                            if (e.NewItems.Count > 0)
                                            {
                                                e.NewItems.ForEachLoop(
                                                    (s, x) =>
                                                    treeViewNode.Nodes.Add(treeNodeToTreeViewNode((BaseStruct.TreeNode)x.Item)));
                                            }
                                        }



                                    });
                            }
                        }
                        break;

                }
            }



        }

        private void tree_Node_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            var treeNode = (BaseStruct.TreeNode)sender;

            lock (_lockObj)
            {
                foreach (var treeView in _treeViews)
                {
                    if (treeView == null)
                    {
                        continue;
                    }
                    switch (e.PropertyName)
                    {
                        case "Text":
                            treeView.Invoke(() =>
                            {
                                treeView.Nodes.Find(treeNode.Key, true).First().Text = treeNode.Text;
                            });

                            break;

                    }
                }
            }


        }


    }
}
